/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.formserver.viewmodel.json.model;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.inspur.edp.cef.designtime.api.json.SerializerUtils;
import com.inspur.edp.das.commonmodel.entity.GspCommonModel;
import com.inspur.edp.das.commonmodel.json.model.CommonModelDeserializer;
import com.inspur.edp.das.commonmodel.json.object.CmObjectDeserializer;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.action.ViewModelAction;
import com.inspur.edp.formserver.viewmodel.collection.VMActionCollection;
import com.inspur.edp.formserver.viewmodel.common.TemplateVoInfo;
import com.inspur.edp.formserver.viewmodel.common.VMAuthConfig;
import com.inspur.edp.formserver.viewmodel.dataextendinfo.VoDataExtendInfo;
import com.inspur.edp.formserver.viewmodel.exception.ViewModelException;
import com.inspur.edp.formserver.viewmodel.exception.VoModelErrorCodes;
import com.inspur.edp.formserver.viewmodel.json.ExtendPropertiesDeserializer;
import com.inspur.edp.formserver.viewmodel.json.ViewModelJsonConst;
import com.inspur.edp.formserver.viewmodel.json.mapping.ViewModelMappingDeserializer;
import com.inspur.edp.formserver.viewmodel.json.object.ViewObjectDeserializer;
import com.inspur.edp.formserver.viewmodel.json.operation.VmActionCollectionDeserializer;
import lombok.SneakyThrows;

import java.io.IOException;
import java.util.HashMap;

/**
 * The  Josn Deserializer Of View Model Definition
 *
 * @ClassName: BizOperationDeserializer
 * @Author: Benjamin Gong
 * @Date: 2021/1/11 17:13
 * @Version: V1.0
 */
public class ViewModelDeserializer extends CommonModelDeserializer {

    @Override
    protected void beforeCMModelDeserializer(GspCommonModel model) {
        GspViewModel vm = (GspViewModel) model;
        vm.setEnableStdTimeFormat(true);
        vm.setAutoConvertMessage(true);
        vm.setDescription("");
        TemplateVoInfo info = new TemplateVoInfo();
        info.setTemplateVoId("");
        info.setTemplateVoPkgName("");
        info.setTemplateVoServiceUnit("");
        vm.setTemplateVoInfo(info);
        vm.setExtendProperties(new HashMap<>());
        VoDataExtendInfo voDataExtendInfo = new VoDataExtendInfo();
        voDataExtendInfo.initVoDataExendInfo(voDataExtendInfo);
        vm.setDataExtendInfo(voDataExtendInfo);
        vm.setActions(new VMActionCollection());
        vm.setSource("");
        vm.setIsGenFilterConvertor(true);
    }

    @Override
    protected GspCommonModel createCommonModel() {
        return new GspViewModel();
    }

    @Override
    protected CmObjectDeserializer createCmObjectDeserializer() {
        return new ViewObjectDeserializer();
    }

    @SneakyThrows
    @Override
    protected boolean readExtendModelProperty(GspCommonModel model, String propertyName,
                                              JsonParser jsonParser) {
        GspViewModel vm = (GspViewModel) model;
        boolean hasProperty = true;
        switch (propertyName) {
            case ViewModelJsonConst.EnableStdTimeFormat:
                vm.setEnableStdTimeFormat(SerializerUtils.readPropertyValue_boolean(jsonParser, false));
                break;
            case ViewModelJsonConst.Description:
                vm.setDescription(SerializerUtils.readPropertyValue_String(jsonParser));
                break;
            case ViewModelJsonConst.Mapping:
                readMapping(jsonParser, vm);
                break;
            case ViewModelJsonConst.ExtendType:
                SerializerUtils.readPropertyValue_String(jsonParser);
                break;
            case ViewModelJsonConst.ValueHelpConfigs:
                readValueHelpConfigs(jsonParser, vm);
                break;
            case ViewModelJsonConst.Actions:
                readVMActions(jsonParser, vm);
                break;
            case ViewModelJsonConst.ExtendProperties:
                readExtendProperties(jsonParser, vm);
                break;
            case ViewModelJsonConst.DataExtendInfo:
                readDataExtendInfo(jsonParser, vm);
                break;
            case ViewModelJsonConst.TemplateVoInfo:
                readTemplateVoInfo(jsonParser, vm);
                break;
            case ViewModelJsonConst.ConvertMsg:
                vm.setAutoConvertMessage(SerializerUtils.readPropertyValue_boolean(jsonParser));
                break;
            case ViewModelJsonConst.Source:
                vm.setSource(SerializerUtils.readPropertyValue_String(jsonParser));
                break;
            case ViewModelJsonConst.IsGenFilterConvertor:
                vm.setIsGenFilterConvertor(SerializerUtils.readPropertyValue_boolean(jsonParser));
                break;
            case ViewModelJsonConst.Auth:
                readVmAuthConfig(jsonParser, vm);
                break;
            default:
                hasProperty = false;
                break;
        }
        return hasProperty;
    }

    private void readVmAuthConfig(JsonParser jsonParser, GspViewModel vm) throws IOException {
        VMAuthConfig config = SerializerUtils.readPropertyValue_Object(VMAuthConfig.class, jsonParser);
        vm.setAuthConfig(config);
        jsonParser.nextToken();
    }

    private void readTemplateVoInfo(JsonParser jsonParser, GspViewModel vm) {
        JsonDeserializer<TemplateVoInfo> deserializer = new JsonDeserializer<TemplateVoInfo>() {
            @Override
            public TemplateVoInfo deserialize(JsonParser p, DeserializationContext ctxt) {
                TemplateVoInfo info = new TemplateVoInfo();
                SerializerUtils.readStartObject(jsonParser);
                while (jsonParser.getCurrentToken() == JsonToken.FIELD_NAME) {
                    String propName = SerializerUtils.readPropertyName(jsonParser);
                    switch (propName) {
                        case ViewModelJsonConst.TemplateVoId:
                            info.setTemplateVoId(SerializerUtils.readPropertyValue_String(jsonParser));
                            break;
                        case ViewModelJsonConst.TemplateVoPkgName:
                            info.setTemplateVoPkgName(SerializerUtils.readPropertyValue_String(jsonParser));
                            break;
                        case ViewModelJsonConst.TemplateVoServiceUnit:
                            info.setTemplateVoServiceUnit(SerializerUtils.readPropertyValue_String(jsonParser));
                            break;
                        default:
                            throw new ViewModelException(VoModelErrorCodes.GSP_VIEWOBJECT_MODEL_1043, null, propName);
                    }
                }
                SerializerUtils.readEndObject(jsonParser);
                return info;
            }
        };
        try {
            vm.setTemplateVoInfo(deserializer.deserialize(jsonParser, null));
        } catch (IOException e) {
            throw new ViewModelException(VoModelErrorCodes.GSP_VIEWOBJECT_MODEL_1044, e, vm.getCode(), vm.getName());
        }
    }

    private void readValueHelpConfigs(JsonParser jsonParser, GspViewModel vm) {
        SerializerUtils
                .readArray(jsonParser, new ValueHelpConfigDeserizlizer(), vm.getValueHelpConfigs());
    }

    private void readMapping(JsonParser jsonParser, GspViewModel vm) {
        ViewModelMappingDeserializer deserializer = new ViewModelMappingDeserializer();
        vm.setMapping(deserializer.deserialize(jsonParser, null));
    }

    private void readVMActions(JsonParser jsonParser, GspViewModel vm) {
        VmActionCollectionDeserializer deserializer = new VmActionCollectionDeserializer();
        VMActionCollection actions = deserializer.deserialize(jsonParser, null);
//    InternalExtendActionUtil internalExtendActionUtil = new InternalExtendActionUtil();
        for (ViewModelAction action : actions) {
//      if(!internalExtendActionUtil.InternalActionIds.contains(action.getID())){
            vm.getActions().add(action);
//      }
        }
    }

    private void initAction(GspViewModel vm) {
        vm.setActions(new VMActionCollection());
    }

    private void readExtendProperties(JsonParser jsonParser, GspViewModel vm) {
        ExtendPropertiesDeserializer deserializer = new ExtendPropertiesDeserializer();
        vm.setExtendProperties(deserializer.deserialize(jsonParser, null));
    }

    private void readDataExtendInfo(JsonParser jsonParser, GspViewModel vm) {
        VoDataExtendInfoDeserializer deserializer = new VoDataExtendInfoDeserializer();
        vm.setDataExtendInfo(deserializer.deserialize(jsonParser, null));
    }
}
